<!DOCTYPE html>
<html lang="en">
<head>
	<title>three.js - gpu particle system</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		body {
			background-color: #000000;
			margin: 0px;
			overflow: hidden;
		}

		a {
			color: #0078ff;
		}

		.dg {
			right: auto!important;
			left: 20px!important;
		}
	</style>
</head>

<body>
	<div style="position: absolute; top: 10px; width: 100%; text-align: center; color:#eee">
		<a href="http://threejs.org" target="_blank">three.js</a> - GPU particle system plugin by <a href="http://charliehoey.com">Charlie Hoey</a>.</div>

	<script src="./build/three.js"></script>
	<script src="./js/controls/TrackballControls.js"></script>
	<script src="./js/libs/dat.gui.min.js"></script>
	<script src="./js/GPUParticleSystem.js" charset="utf-8"></script>

	<script>
		var camera, tick = 0,
			scene, renderer, clock = new THREE.Clock(true),
			controls, container, gui = new dat.GUI(),
			options, spawnerOptions, particleSystem;

		init();
		animate();

		function init() {


			container = document.createElement('div');
			document.body.appendChild(container);

			camera = new THREE.PerspectiveCamera(28, window.innerWidth / window.innerHeight, 5, 100000);
			camera.position.z = 100;

			scene = new THREE.Scene();

			// The GPU Particle system extends THREE.Object3D, and so you can use it
			// as you would any other scene graph component.	Particle positions will be
			// relative to the position of the particle system, but you will probably only need one
			// system for your whole scene
			particleSystem = new THREE.GPUParticleSystem({
				maxParticles: 250000
			});
			scene.add( particleSystem);


			// options passed during each spawned
			options = {
				position: new THREE.Vector3(),
				positionRandomness: .3,
				velocity: new THREE.Vector3(),
				velocityRandomness: .5,
				color: 0xaa88ff,
				colorRandomness: .2,
				turbulence: .5,
				lifetime: 2,
				size: 5,
				sizeRandomness: 1
			};

			spawnerOptions = {
				spawnRate: 15000,
				horizontalSpeed: 1.5,
				verticalSpeed: 1.33,
				timeScale: 1
			};

			gui.add(options, "velocityRandomness", 0, 3);
			gui.add(options, "positionRandomness", 0, 3);
			gui.add(options, "size", 1, 20);
			gui.add(options, "sizeRandomness", 0, 25);
			gui.add(options, "colorRandomness", 0, 1);
			gui.add(options, "lifetime", .1, 10);
			gui.add(options, "turbulence", 0, 1);

			gui.add(spawnerOptions, "spawnRate", 10, 30000);
			gui.add(spawnerOptions, "timeScale", -1, 1);

			renderer = new THREE.WebGLRenderer();
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(window.innerWidth, window.innerHeight);
			container.appendChild(renderer.domElement);

			// setup controls
			controls = new THREE.TrackballControls(camera, renderer.domElement);
			controls.rotateSpeed = 5.0;
			controls.zoomSpeed = 2.2;
			controls.panSpeed = 1;
			controls.dynamicDampingFactor = 0.3;

			window.addEventListener('resize', onWindowResize, false);

		}

		function onWindowResize() {

			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();

			renderer.setSize(window.innerWidth, window.innerHeight);

		}

		function animate() {

			requestAnimationFrame(animate);

			controls.update();

			var delta = clock.getDelta() * spawnerOptions.timeScale;
			tick += delta;

			if (tick < 0) tick = 0;

			if (delta > 0) {
				options.position.x = Math.sin(tick * spawnerOptions.horizontalSpeed) * 20;
				options.position.y = Math.sin(tick * spawnerOptions.verticalSpeed) * 10;
				options.position.z = Math.sin(tick * spawnerOptions.horizontalSpeed + spawnerOptions.verticalSpeed) * 5;

				for (var x = 0; x < spawnerOptions.spawnRate * delta; x++) {
					// Yep, that's really it.	Spawning particles is super cheap, and once you spawn them, the rest of
					// their lifecycle is handled entirely on the GPU, driven by a time uniform updated below
					particleSystem.spawnParticle(options);
				}
			}

			particleSystem.update(tick);

			render();

		}

		function render() {

			renderer.render(scene, camera);

		}
	</script>
</body>

</html>
